/**
 * 
 */
package com.syncshot.androidapp.activities;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.TextView;

import com.syncshot.androidapp.Constant;
import com.syncshot.androidapp.R;

/**
 * @author Stan
 * 
 */
public class TakePictureActivity extends AbstractActivity {
    /** Used locally to tag Logs */
    @SuppressWarnings("unused")
    private static final String TAG                    = "TakePictureActivity";

    public static final String KEY_TAKEPICT_TIMESTAMP = "takePictTimeStamp";

    private Camera              mCamera;
    private CameraPreview       mPreview;
    public static final int     MEDIA_TYPE_IMAGE       = 1;
    PictureCallback             mPicture;

    private int                 num;
    private Timer               compteur;
    private Animation           inNum;
    private Animation           outNum;

    private TextView            numero1;
    private TextView            numero2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.take_picture);

        SharedPreferences settings = getSharedPreferences(Constant.PREF, 0);
        int diffSaved = settings.getInt(Constant.PREF_DIFF_SERVERTIME, Integer.MAX_VALUE);
        long takePict = getIntent().getLongExtra(KEY_TAKEPICT_TIMESTAMP, 0);
        int diff = (int) (diffSaved - takePict - System.currentTimeMillis());
        if ((diff <= 0) || (diff > 10000)) {
            diff = 5320;
        }

        // is camera is ok, start it
        if (checkCameraHardware(this)) {
            mCamera = getCameraInstance();

            // Create our Preview view and set it as the content of our activity.
            if (mCamera != null) {
                mPreview = new CameraPreview(this, mCamera);
                FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
                preview.addView(mPreview);
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (mCamera != null) {
                            mCamera.takePicture(null, null, mPicture);
                        }
                    }
                }, diff);
            }
        }

        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
            display.getSize(size);
        } else {
            size.x = display.getWidth(); // deprecated
            size.y = display.getHeight(); // deprecated
        }
        int h = ((size.y - size.x) / 2);
        findViewById(R.id.picture_layout_header).getLayoutParams().height = h;
        findViewById(R.id.picture_layout_footer).getLayoutParams().height = h;

        mPicture = new PictureCallback() {

            public void onPictureTaken(byte[] data, Camera camera) {
            	
            	NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
            	nm.cancel(0);

                File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);

                String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
                File file = new File(path, "IMG_" + timeStamp + ".jpg");

                Options opts = new Options();
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts);
                int w = bitmap.getWidth();
                int h = bitmap.getHeight();

                float aspect = (float) h / w;
                float scaleHeight = 640;
                float scaleWidth = scaleHeight / aspect;
                Matrix matrix = new Matrix();
                matrix.postRotate(90);
                matrix.postScale(scaleWidth / w, scaleHeight / h);

                int x = (int) Math.abs(scaleHeight - scaleWidth) / 2;

                final Bitmap scaledImage = Bitmap.createBitmap(bitmap, x, 0, (int)(Math.min(640, scaleWidth) / (scaleWidth / w)), (int)(Math.min(640, scaleHeight) / (scaleHeight / h)), matrix, false);
                bitmap.recycle();

                try {
                    path.mkdirs();
                    OutputStream os = new FileOutputStream(file);
                    scaledImage.compress(CompressFormat.JPEG, 75, os);
                    // os.write(data);
                    os.close();

                    // Tell the media scanner about the new file so that it is
                    // immediately available to the user.
                    MediaScannerConnection.scanFile(TakePictureActivity.this, new String[] { file.toString() }, null, new MediaScannerConnection.OnScanCompletedListener() {
                        public void onScanCompleted(String path, Uri uri) {
                            Log.i("ExternalStorage", "Scanned " + path + ":");
                            Log.i("ExternalStorage", "-> uri=" + uri);

                            Intent uploadIntent = new Intent();
                            uploadIntent.setClassName("com.syncshot.androidapp", "com.syncshot.androidapp.service.HttpUploader");
                            // uploadIntent.setClassName("com.test.upload", "com.test.upload.HttpUploader");
                            uploadIntent.setData(uri);
                            String eventId = getIntent().getStringExtra(Constant.KEY_EVENT_ID);
                            if(eventId == null) {
                                eventId = "1";
                            }
                            uploadIntent.putExtra(Constant.KEY_EVENT_ID, eventId);
                            startService(uploadIntent);
                            
                            Intent intent = new Intent(TakePictureActivity.this, PictureWaitUploadActivity.class);
                            intent.setData(uri);
                            intent.putExtra(Constant.KEY_EVENT_ID, eventId);
                            startActivity(intent);
                            finish();
                        }
                    });

                } catch (IOException e) {
                    // Unable to create file, likely because external storage is
                    // not currently mounted.
                    Log.w("ExternalStorage", "Error writing " + file, e);
                }
            }
        };

        num = diff / 1000;
        numero1 = (TextView) findViewById(R.id.counter_textview);
        numero2 = (TextView) findViewById(R.id.counter2_textview);
        numero2.setVisibility(View.INVISIBLE);
        inNum = AnimationUtils.loadAnimation(this, R.anim.crossnum_in);
        outNum = AnimationUtils.loadAnimation(this, R.anim.crossnum_out);

        Animation initAnim = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_SELF, 00.0f, Animation.RELATIVE_TO_SELF, 0.5f);
        initAnim.setDuration(0);
        initAnim.setFillEnabled(true);
        initAnim.setFillAfter(true);
        numero1.startAnimation(initAnim);
        numero2.setText(String.valueOf(num));
        numero1.setText(String.valueOf(num));

        inNum.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation arg0) {
                numero2.setText(String.valueOf(num));
            }

            @Override
            public void onAnimationRepeat(Animation arg0) {
            }

            @Override
            public void onAnimationEnd(Animation arg0) {
                numero1.setText(String.valueOf(num));
            }
        });

        outNum.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation arg0) {
            }

            @Override
            public void onAnimationRepeat(Animation arg0) {
            }

            @Override
            public void onAnimationEnd(Animation arg0) {
            }
        });

        compteur = new Timer(false);
        compteur.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        changeNum(num - 1);
                    }
                });
            }
        }, (diff - (diff / 1000) * 1000), 1000);

    }

    @Override
    protected void onPause() {
        super.onPause();
        releaseCamera();
    }

    public void changeNum(int newNum) {
        num = newNum;
        numero1.startAnimation(outNum);
        numero2.startAnimation(this.inNum);

        if (num == 0) {
            compteur.cancel();
        }
    }

    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            return true;
        } else {
            return false;
        }
    }

    private static Camera getCameraInstance() {
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e) {
            // Camera is not available (in use or does not exist)
            e.printStackTrace();
        }
        return c;
    }

    /** A basic Camera preview class */
    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private Camera        mCamera;

        public CameraPreview(Context context, Camera camera) {
            super(context);
            mCamera = camera;
            mCamera.setDisplayOrientation(90);
            Parameters p = mCamera.getParameters();
            if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
                p.setFlashMode(Parameters.FLASH_MODE_TORCH);
            }
            p.set("jpeg-quality", 70);
            p.setPictureFormat(PixelFormat.JPEG);

            List<Size> sizes = p.getSupportedPictureSizes();
            if (sizes != null) {
                Size sizeSelected = null;
                Collections.sort(sizes, new Comparator<Size>() {
                    @Override
                    public int compare(Size lhs, Size rhs) {
                        return Math.min(lhs.height, lhs.width) - Math.min(rhs.height, rhs.width);
                    }
                });
                for (Size size : sizes) {
                    Log.v(TAG, "size : " + size.height + " x " + size.width);
                    if (Math.min(size.height, size.width) >= 640) {
                        sizeSelected = size;
                        break;
                    }
                }
                if (sizeSelected != null) {
                    p.setPictureSize(sizeSelected.width, sizeSelected.height);
                }
            }
            mCamera.setParameters(p);

            // Install a SurfaceHolder.Callback so we get notified when the
            // underlying surface is created and destroyed.
            mHolder = getHolder();
            mHolder.addCallback(this);
            // deprecated setting, but required on Android versions prior to 3.0
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        public void surfaceCreated(SurfaceHolder holder) {
            // The Surface has been created, now tell the camera where to draw the preview.
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
                Log.d(TAG, "Error setting camera preview: " + e.getMessage());
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            mCamera.release();

        }

        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            // If your preview can change or rotate, take care of those events here.
            // Make sure to stop the preview before resizing or reformatting it.

            if (mHolder.getSurface() == null) {
                // preview surface does not exist
                return;
            }

            // stop preview before making changes
            try {
                mCamera.stopPreview();
            } catch (Exception e) {
                // ignore: tried to stop a non-existent preview
            }

            // set preview size and make any resize, rotate or
            // reformatting changes here

            // start preview with new settings
            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();

            } catch (Exception e) {
                Log.d(TAG, "Error starting camera preview: " + e.getMessage());
            }
        }
    }

    private void releaseCamera() {
        if (mCamera != null) {
            mCamera.release();
            mCamera = null;
        }
    }

}
